 package xin.petstore.framework.web.page;
 
 import xin.petstore.framework.file.hash.FileHashUtils;
 import com.mongodb.gridfs.GridFSFile;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;


 import java.util.Iterator;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.apache.commons.io.FileUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.data.mongodb.gridfs.GridFsTemplate;
 import org.springframework.util.Assert;
 
 public class PageBeanPostProcessor
   implements InitializingBean
 {
   private static final Logger logger = LoggerFactory.getLogger(PageBeanPostProcessor.class);
   private static final String patternImg = "<img\\s+[^>]*?src=\"((\\w+?:?//|\\/|\\w*)[^\"]*?)\"[^>]*?>";
   private static final String patternLink = "<link\\s+[^>]*?href=[\"|']((\\w+?:?//|\\/|\\w*)[^\"]*?)[\"|'][^>]*?>";
   private static final String patternScript = "<script\\s+[^>]*?src=[\"|']((\\w+?:?//|\\/|\\w*)[^\"]*?)[\"|'][^>]*?>";
   private String replaceHttp;
   private String sysType;
   private String version;
   private String[] resourcesRootPath;
   private String[] replacePath;
   private MongoTemplate mongoTemplate;
   private GridFsTemplate gridFsTemplate;
 
   public void afterPropertiesSet()
     throws Exception
   {
     Assert.notNull(this.mongoTemplate, "mongoTemplate is not null.");
     Assert.notNull(this.gridFsTemplate, "gridFsTemplate is not null.");
     Assert.notNull(this.resourcesRootPath, "resourcesRootPath is not null.");
     Assert.notNull(this.sysType, "sysType is not null.");
     Assert.notNull(this.replacePath, "replacePath is not null.");
     SystemInfo si = (SystemInfo)this.mongoTemplate.findOne(Query.query(Criteria.where("sysType").is(this.sysType).and("version").is(this.version)), SystemInfo.class);
     try
     {
       String classPath = Thread.currentThread().getContextClassLoader().getResource("/").getPath();
       String webRootPath = classPath.substring(0, classPath.indexOf("WEB-INF"));
       if (si == null) {
         for (String path : this.resourcesRootPath) {
           String dir = webRootPath + path;
           if (logger.isInfoEnabled()) {
             logger.info("resourcesRootPath:{}", dir);
           }
           File f = new File(dir);
           if (f.isDirectory()) {
             Iterator files = FileUtils.iterateFiles(f, 
               new String[] { "js", "css", "jpg", "gif", "png" }, true);
             while (files.hasNext()) {
               File ff = (File)files.next();
               String hash = FileHashUtils.getMD5HashValue(ff);
               String relativeUrl = ff.getPath().replaceAll("\\\\", "/");
               relativeUrl = relativeUrl.substring(relativeUrl.indexOf(path));
 
               FileInfo fi = (FileInfo)this.mongoTemplate.findOne(Query.query(Criteria.where("sysType").is(this.sysType).and("fileUrl").is(relativeUrl)), FileInfo.class);
               if (fi != null) {
                 if (!hash.equalsIgnoreCase(fi.getHashcode())) {
                   String s = relativeUrl.substring(0, relativeUrl.indexOf(".")) + "_" + fi.getHashcode() + relativeUrl.substring(relativeUrl.indexOf("."));
                   GridFSFile gf = this.gridFsTemplate.store(new FileInputStream(ff), s);
                   TargetFile tf = new TargetFile();
                   tf.setFileId(gf.getId().toString());
                   tf.setFileUrl(s);
                   tf.setOriginalFileInfoId(fi.getId());
                   if (logger.isInfoEnabled()) {
                     logger.info("update relativeUrl:{}", s);
                   }
                   Update update = new Update();
                   update.set("hashcode", hash);
                   this.mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(fi.getId())), update, FileInfo.class);
                 }
               } else {
                 FileInfo fio = new FileInfo();
                 fio.setFileUrl(relativeUrl);
                 fio.setHashcode(hash);
                 fio.setSysType(this.sysType);
                 this.mongoTemplate.save(fio);
                 String s = relativeUrl.substring(0, relativeUrl.indexOf(".")) + "_" + hash + relativeUrl.substring(relativeUrl.indexOf("."));
                 GridFSFile gf = this.gridFsTemplate.store(new FileInputStream(ff), s);
                 TargetFile tf = new TargetFile();
                 tf.setFileId(gf.getId().toString());
                 tf.setFileUrl(s);
                 tf.setOriginalFileInfoId(fio.getId());
                 if (logger.isInfoEnabled()) {
                   logger.info("new relativeUrl:{}", relativeUrl);
                 }
                 this.mongoTemplate.save(tf);
               }
             }
           }
         }
 
         SystemInfo s = new SystemInfo();
         s.setDeploy(true);
         s.setSysType(this.sysType);
         s.setVersion(this.version);
         this.mongoTemplate.save(s);
       }
       for (String path : this.replacePath) {
         String dir = webRootPath + path;
         if (logger.isInfoEnabled()) {
           logger.info("replacePath:{}", dir);
         }
         File f = new File(dir);
         if (f.isDirectory()) {
           Iterator files = FileUtils.iterateFiles(f, 
             new String[] { "html", "ftl", "jsp" }, true);
           while (files.hasNext()) {
             File ff = (File)files.next();
             String content = FileUtils.readFileToString(ff, "utf-8");
             content = replace(content, "<img\\s+[^>]*?src=\"((\\w+?:?//|\\/|\\w*)[^\"]*?)\"[^>]*?>");
             content = replace(content, "<link\\s+[^>]*?href=[\"|']((\\w+?:?//|\\/|\\w*)[^\"]*?)[\"|'][^>]*?>");
             content = replace(content, "<script\\s+[^>]*?src=[\"|']((\\w+?:?//|\\/|\\w*)[^\"]*?)[\"|'][^>]*?>");
             System.out.println(content);
             String url = ff.getPath();
             FileUtils.write(ff, content, "utf-8");
             if (logger.isInfoEnabled())
               logger.info("replace File:{}", url);
           }
         }
       }
     }
     catch (IOException e) {
       e.printStackTrace();
     }
   }
 
   private boolean isRootStart(String url) {
     for (String path : this.resourcesRootPath) {
       if (url.startsWith(path)) {
         return true;
       }
     }
     return false;
   }
 
   private String replaceRootStart(String url) {
     for (String path : this.resourcesRootPath) {
       if (url.contains(path)) {
         return url.substring(url.indexOf(path));
       }
       url = url + "/";
       if (url.contains(path)) {
         return url.substring(url.indexOf(path));
       }
     }
     return null;
   }
   private String repl(String content, String url, String replaceHttp) {
     if (logger.isInfoEnabled()) {
       logger.info("url:{}  replaceHttp:{}", url, replaceHttp);
     }
     return content.replaceAll(url, replaceHttp);
   }
   private String handleUrl(String content, String url) {
     if (!url.startsWith("http://")) {
       if (isRootStart(url)) {
         FileInfo fi = (FileInfo)this.mongoTemplate.findOne(Query.query(Criteria.where("sysType").is(this.sysType).and("fileUrl").is(url)), FileInfo.class);
         if (fi == null) {
           content = repl(content, url, this.replaceHttp + url);
         } else {
           String s = url.substring(0, url.indexOf(".")) + "_" + fi.getHashcode() + url.substring(url.indexOf("."));
           content = repl(content, url, this.replaceHttp + s);
         }
       }
       else {
         String r_url = replaceRootStart(url);
         if (r_url != null) {
           FileInfo fi = (FileInfo)this.mongoTemplate.findOne(Query.query(Criteria.where("sysType").is(this.sysType).and("fileUrl").is(r_url)), FileInfo.class);
           if (fi == null) {
             content = repl(content, url, this.replaceHttp + r_url);
           } else {
             String s = r_url.substring(0, r_url.indexOf(".")) + "_" + fi.getHashcode() + r_url.substring(r_url.indexOf("."));
             content = repl(content, url, this.replaceHttp + s);
           }
         }
       }
     }
 
     return content;
   }
   private String replace(String content, String patternStr) {
     Pattern pattern = Pattern.compile(patternStr);
     Matcher matcher = pattern.matcher(content);
     while (matcher.find()) {
       String url = matcher.group(1);
       content = handleUrl(content, url);
     }
     return content;
   }
   public String getReplaceHttp() {
     return this.replaceHttp;
   }
 
   public void setReplaceHttp(String replaceHttp) {
     this.replaceHttp = replaceHttp;
   }
 
   public String getSysType() {
     return this.sysType;
   }
 
   public void setSysType(String sysType) {
     this.sysType = sysType;
   }
 
   public String getVersion() {
     return this.version;
   }
 
   public void setVersion(String version) {
     this.version = version;
   }
 
   public String[] getResourcesRootPath() {
     return this.resourcesRootPath;
   }
 
   public void setResourcesRootPath(String[] resourcesRootPath) {
     this.resourcesRootPath = resourcesRootPath;
   }
 
   public String[] getReplacePath() {
     return this.replacePath;
   }
 
   public void setReplacePath(String[] replacePath) {
     this.replacePath = replacePath;
   }
 
   public MongoTemplate getMongoTemplate() {
     return this.mongoTemplate;
   }
 
   public void setMongoTemplate(MongoTemplate mongoTemplate) {
     this.mongoTemplate = mongoTemplate;
   }
 
   public GridFsTemplate getGridFsTemplate() {
     return this.gridFsTemplate;
   }
 
   public void setGridFsTemplate(GridFsTemplate gridFsTemplate) {
     this.gridFsTemplate = gridFsTemplate;
   }
 }
